#!/bin/bash
# ============================================================================
# Скрипт базовой настройки DNS-сервера BIND
# Требует прав root. Работает на RHEL/CentOS/Fedora (проверено на RHEL 8/9)
# ============================================================================
set -euo pipefail

# === КОНФИГУРАЦИЯ (измените значения под вашу среду) ===
DNS_SERVER_IP="192.168.0.1"          # IP-адрес сервера для прослушивания
DOMAIN="example.org"                # Имя локальной зоны
ALLOW_QUERY="any"                   # Сеть для запросов (пример: 192.168.0.0/24)
FORWARDERS="8.8.8.8; 8.8.4.4;"      # Адреса внешних DNS-серверов
REVERSE_ZONE="10.168.192.in-addr.arpa"  # Обратная зона для сети 192.168.10.0/24
# =======================================================

# Проверка прав root
if [[ $EUID -ne 0 ]]; then
    echo "❌ Ошибка: Скрипт должен запускаться от имени root (sudo)"
    exit 1
fi

# Проверка установки BIND
if ! rpm -q bind &>/dev/null; then
    echo "⚠️  BIND не установлен. Установка..."
    dnf install -y bind bind-utils || yum install -y bind bind-utils
fi

# Резервная копия конфигурации
NAMED_CONF="/etc/named.conf"
BACKUP_FILE="${NAMED_CONF}.backup.$(date +%Y%m%d_%H%M%S)"
cp -f "$NAMED_CONF" "$BACKUP_FILE"
echo "✅ Создана резервная копия: $BACKUP_FILE"

# Создание директории для зон
ZONE_MASTER_DIR="/var/named/master"
mkdir -p "$ZONE_MASTER_DIR"

# === Настройка прямой зоны ===
ZONE_FILE_FORWARD="${ZONE_MASTER_DIR}/${DOMAIN}"
cat > "$ZONE_FILE_FORWARD" <<EOF
\$TTL 604800
${DOMAIN}.    IN      SOA     ns01.${DOMAIN}. root.${DOMAIN}. (
                1       ; Serial
                600     ; Refresh
                3600    ; Retry
                1w      ; Expire
                360     ; Minimum TTL
                )

        IN      NS      ns01.${DOMAIN}.
        IN      NS      ns02.${DOMAIN}.
        IN      NS      ns03.${DOMAIN}.
        IN      NS      test.${DOMAIN}.

ns01    IN      A       192.168.10.50
ns02    IN      A       192.168.10.60
ns03    IN      A       192.168.10.70
test    IN      A       192.168.10.12

; SRV Records for LDAP
_ldap._tcp.${DOMAIN}. 3600 IN SRV 0 0 389 ns01.${DOMAIN}.
EOF
echo "✅ Создана прямая зона: $ZONE_FILE_FORWARD"

# === Настройка обратной зоны ===
ZONE_FILE_REVERSE="${ZONE_MASTER_DIR}/${REVERSE_ZONE//.in-addr.arpa/}.zone"
cat > "$ZONE_FILE_REVERSE" <<EOF
\$TTL 3600
@     IN      SOA     ${DOMAIN}. root.${DOMAIN}. (
      20060204        ; Serial
      3600            ; Refresh
      900             ; Retry
      3600000         ; Expire
      3600            ; Minimum
      )
@     IN      NS      localhost.
50    IN      PTR     ns01.${DOMAIN}.
60    IN      PTR     ns02.${DOMAIN}.
70    IN      PTR     ns03.${DOMAIN}.
12    IN      PTR     test.${DOMAIN}.
EOF
echo "✅ Создана обратная зона: $ZONE_FILE_REVERSE"

# Настройка прав доступа
chown -R root:named "$ZONE_MASTER_DIR"
chmod 0640 "$ZONE_MASTER_DIR"/*
echo "✅ Установлены права на зоны: root:named, 0640"

# Создание директории для логов
LOG_DIR="/var/log/bind"
mkdir -p "$LOG_DIR"
chown named:named "$LOG_DIR"
chmod 750 "$LOG_DIR"
echo "✅ Настроена директория логов: $LOG_DIR"

# === Формирование нового конфигурационного файла ===
cat > "$NAMED_CONF" <<EOF
options {
        listen-on port 53 { 127.0.0.1; ${DNS_SERVER_IP}; };
        listen-on-v6 port 53 { none; };
        directory       "/var/named";
        dump-file       "/var/named/data/cache_dump.db";
        statistics-file "/var/named/data/named_stats.txt";
        memstatistics-file "/var/named/data/named_mem_stats.txt";
        allow-query     { ${ALLOW_QUERY}; };
        forward first;
        forwarders { ${FORWARDERS} };
        recursion yes;
        dnssec-enable yes;
        dnssec-validation yes;
        bindkeys-file "/var/named/named.iscdlv.key";
        managed-keys-directory "/var/named/dynamic";
        pid-file "/run/named/named.pid";
        session-keyfile "/run/named/session.key";
};

logging {
        channel "misc" {
                file "/var/log/bind/misc.log" versions 4 size 4m;
                print-time yes;
                print-severity yes;
                print-category yes;
        };

        channel "query" {
                file "/var/log/bind/query.log" versions 4 size 4m;
                print-time yes;
                print-severity no;
                print-category no;
        };

        category default { "misc"; };
        category queries { "query"; };
};

zone "${DOMAIN}" {
        type master;
        file "master/${DOMAIN}";
};

zone "${REVERSE_ZONE}" {
        type master;
        file "master/${ZONE_FILE_REVERSE##*/}";
};

include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";
EOF
echo "✅ Обновлён конфигурационный файл: $NAMED_CONF"

# Проверка синтаксиса конфигурации
if ! named-checkconf "$NAMED_CONF" 2>/dev/null; then
    echo "❌ Ошибка синтаксиса в конфигурации! Восстанавливаем резервную копию..."
    cp -f "$BACKUP_FILE" "$NAMED_CONF"
    exit 1
fi

# Перезапуск службы
systemctl restart named
systemctl enable named --now

# Проверка статуса
if systemctl is-active --quiet named; then
    echo -e "\n✅ DNS-сервер успешно запущен!"
    echo -e "\n🔍 Проверка работоспособности:"
    echo "   nslookup test.${DOMAIN} ${DNS_SERVER_IP}"
    echo "   dig @${DNS_SERVER_IP} _ldap._tcp.${DOMAIN} SRV"
    echo "   nslookup 192.168.10.50 ${DNS_SERVER_IP}"
    echo -e "\n📄 Логи:"
    echo "   tail -f /var/log/bind/query.log"
else
    echo "❌ Не удалось запустить службу named. Проверьте логи:"
    journalctl -u named -n 50 --no-pager
    exit 1
fi